﻿#include "DANodeItemSettingWidget.h"
#include <QDebug>
#include "ui_DANodeItemSettingWidget.h"
#include "DANodeGraphicsScene.h"
#include "DAGraphicsResizeableItem.h"
#include "DACommandsForGraphics.h"
#include <QSignalBlocker>
////////////////////////////////////////////////
///
////////////////////////////////////////////////

using namespace DA;

////////////////////////////////////////////////
/// DANodeItemSettingWidget
////////////////////////////////////////////////
DANodeItemSettingWidget::DANodeItemSettingWidget(QWidget* parent)
    : QWidget(parent), ui(new Ui::DANodeItemSettingWidget), _item(nullptr), _scene(nullptr)
{
    ui->setupUi(this);
    connect(ui->doubleSpinBoxBodyWidth,
            QOverload< double >::of(&QDoubleSpinBox::valueChanged),
            this,
            &DANodeItemSettingWidget::onDoubleSpinBoxBodyWidthValueChanged);
    connect(ui->doubleSpinBoxBodyHeight,
            QOverload< double >::of(&QDoubleSpinBox::valueChanged),
            this,
            &DANodeItemSettingWidget::onDoubleSpinBoxBodyHeightValueChanged);
    connect(ui->doubleSpinBoxRotation,
            QOverload< double >::of(&QDoubleSpinBox::valueChanged),
            this,
            &DANodeItemSettingWidget::onDoubleSpinBoxRotationValueChanged);
    connect(ui->doubleSpinBoxX, QOverload< double >::of(&QDoubleSpinBox::valueChanged), this, &DANodeItemSettingWidget::onDoubleSpinBoxXValueChanged);
    connect(ui->doubleSpinBoxY, QOverload< double >::of(&QDoubleSpinBox::valueChanged), this, &DANodeItemSettingWidget::onDoubleSpinBoxYValueChanged);
    connect(ui->checkBoxMovable, &QCheckBox::stateChanged, this, &DANodeItemSettingWidget::onCheckBoxMovableStateChanged);
    connect(ui->checkBoxResizable, &QCheckBox::stateChanged, this, &DANodeItemSettingWidget::onCheckBoxResizableStateChanged);
}

DANodeItemSettingWidget::~DANodeItemSettingWidget()
{
    delete ui;
}

void DANodeItemSettingWidget::setItem(DAGraphicsResizeableItem* item)
{
    _item = item;
    updateData();
}
/**
 * @brief 获取维护的item
 * @return
 */
DAGraphicsResizeableItem* DANodeItemSettingWidget::getItem() const
{
    return _item;
}

/**
 * @brief 设置了scene能实现redo/undo
 *
 * 如果设置nullptr，将不使用redo/undo
 * @param sc
 */
void DANodeItemSettingWidget::setScene(DANodeGraphicsScene* sc)
{
    if (_scene) {
        disconnect(_scene, &DANodeGraphicsScene::nodeItemsRemoved, this, &DANodeItemSettingWidget::onNodeItemsRemoved);
    }
    _scene = sc;
    if (_scene) {
        connect(_scene, &DANodeGraphicsScene::nodeItemsRemoved, this, &DANodeItemSettingWidget::onNodeItemsRemoved);
    }
}

void DANodeItemSettingWidget::updateData()
{
    if (nullptr == _item) {
        resetValue();
        return;
    }
    updatePosition();
    updateBodySize();
    updateItemState();
    updateRotation();
}

void DANodeItemSettingWidget::updatePosition()
{
    QSignalBlocker b1(ui->doubleSpinBoxX), b2(ui->doubleSpinBoxY);
    Q_UNUSED(b1);
    Q_UNUSED(b2);
    ui->doubleSpinBoxX->setValue(_item->x());
    ui->doubleSpinBoxY->setValue(_item->y());
}

void DANodeItemSettingWidget::updateRotation()
{
    QSignalBlocker b1(ui->doubleSpinBoxRotation);
    Q_UNUSED(b1);
    ui->doubleSpinBoxRotation->setValue(_item->rotation());
}

void DANodeItemSettingWidget::updateBodySize()
{
    QSignalBlocker b1(ui->doubleSpinBoxBodyWidth), b2(ui->doubleSpinBoxBodyHeight);
    Q_UNUSED(b1);
    Q_UNUSED(b2);
    QSizeF originSize = _item->getBodySize();
    QSizeF minSize    = _item->getBodyMinimumSize();
    QSizeF maxSize    = _item->getBodyMaximumSize();
    ui->doubleSpinBoxBodyWidth->setValue(originSize.width());
    ui->doubleSpinBoxBodyWidth->setMinimum(minSize.width());
    ui->doubleSpinBoxBodyWidth->setMaximum(maxSize.width());
    ui->doubleSpinBoxBodyHeight->setValue(originSize.height());
    ui->doubleSpinBoxBodyHeight->setMinimum(minSize.height());
    ui->doubleSpinBoxBodyHeight->setMaximum(maxSize.height());
}

void DANodeItemSettingWidget::updateItemState()
{
    QSignalBlocker b1(ui->checkBoxMovable), b2(ui->checkBoxResizable);
    Q_UNUSED(b1);
    Q_UNUSED(b2);
    //网格的尺寸作为x,y的步长
    if (_scene) {
        QSize gs = _scene->getGridSize();
        ui->doubleSpinBoxX->setSingleStep(gs.width());
        ui->doubleSpinBoxY->setSingleStep(gs.height());
    }
    ui->checkBoxMovable->setChecked(_item->isMovable());
    ui->checkBoxResizable->setChecked(_item->isEnableResize());
    ui->doubleSpinBoxBodyWidth->setEnabled(_item->isEnableResize());
    ui->doubleSpinBoxBodyHeight->setEnabled(_item->isEnableResize());
    ui->doubleSpinBoxX->setEnabled(_item->isMovable());
    ui->doubleSpinBoxY->setEnabled(_item->isMovable());
    ui->textEdit->setText(_item->toolTip());
}

void DANodeItemSettingWidget::onDoubleSpinBoxBodyWidthValueChanged(double v)
{
    if (nullptr == _item) {
        return;
    }
    QSizeF originSize = _item->getBodySize();
    if (ui->checkBoxLockAspectRatio->isChecked()) {
        _item->setBodySize(originSize.scaled(v, originSize.height(), Qt::KeepAspectRatio));
    } else {
        _item->setBodySize(QSizeF(v, originSize.height()));
    }
    QSizeF settedSize = _item->getBodySize();

    QSignalBlocker b1(ui->doubleSpinBoxBodyWidth), b2(ui->doubleSpinBoxBodyHeight);
    ui->doubleSpinBoxBodyWidth->setValue(settedSize.width());
    ui->doubleSpinBoxBodyHeight->setValue(settedSize.height());
    if (_scene) {
        //如果有scene，就把结果推入cmd,注意因为已经设置了bodysize，因此skipFirst一定要为true
        if (originSize != settedSize) {
            auto cmd = new DA::DACommandsForGraphicsItemResized(_item, originSize, settedSize, true);
            _scene->push(cmd);
        }
    }
}

void DANodeItemSettingWidget::onDoubleSpinBoxBodyHeightValueChanged(double v)
{
    if (nullptr == _item) {
        return;
    }
    QSizeF originSize = _item->getBodySize();
    if (ui->checkBoxLockAspectRatio->isChecked()) {
        _item->setBodySize(originSize.scaled(originSize.width(), v, Qt::KeepAspectRatio));
    } else {
        _item->setBodySize(QSizeF(originSize.width(), v));
    }
    QSizeF settedSize = _item->getBodySize();
    //设置成功了，设置高度
    QSignalBlocker b1(ui->doubleSpinBoxBodyWidth), b2(ui->doubleSpinBoxBodyHeight);
    ui->doubleSpinBoxBodyWidth->setValue(settedSize.width());
    ui->doubleSpinBoxBodyHeight->setValue(settedSize.height());
    if (_scene) {
        //如果有scene，就把结果推入cmd,注意因为已经设置了bodysize，因此skipFirst一定要为true
        if (_item->getBodySize().height() == originSize.height()) {
            //说明没设置成功,跳过
            return;
        }
        auto cmd = new DA::DACommandsForGraphicsItemResized(_item, originSize, settedSize, true);
        _scene->push(cmd);
    }
}

void DANodeItemSettingWidget::onDoubleSpinBoxRotationValueChanged(double v)
{
    if (nullptr == _item) {
        return;
    }
    qreal oldRotation = _item->rotation();
    if (qFuzzyCompare(oldRotation, v)) {
        qDebug() << "same rotation value , skip";
        return;
    }
    _item->setRotation(v);
    if (_scene) {
        //如果有scene，就把结果推入cmd,注意因为已经设置了bodysize，因此skipFirst一定要为true
        if (!qFuzzyCompare(_item->rotation(), v)) {
            //说明没设置成功,跳过
            qDebug() << "_item rotation value not equal setting value";
            QSignalBlocker b(ui->doubleSpinBoxRotation);
            Q_UNUSED(b);
            ui->doubleSpinBoxRotation->setValue(_item->rotation());
            return;
        }
        auto cmd = new DA::DACommandsForGraphicsItemRotation(_item, oldRotation, v, true);
        _scene->push(cmd);
    }
}

void DANodeItemSettingWidget::onDoubleSpinBoxXValueChanged(double v)
{
    if (nullptr == _item) {
        return;
    }
    QPointF oldpos = _item->pos();
    _item->setPos(v, oldpos.y());
    QPointF newPos = _item->pos();
    //在存在网格的情况下，可能设置的位置不是显示的位置，
    QSignalBlocker b1(ui->doubleSpinBoxX), b2(ui->doubleSpinBoxY);
    Q_UNUSED(b1);
    Q_UNUSED(b2);
    ui->doubleSpinBoxX->setValue(newPos.x());
    ui->doubleSpinBoxY->setValue(newPos.y());
    if (_scene) {
        auto cmd = new DA::DACommandsForGraphicsItemMoved(_item, oldpos, newPos, true);
        _scene->push(cmd);
    }
}

void DANodeItemSettingWidget::onDoubleSpinBoxYValueChanged(double v)
{
    if (nullptr == _item) {
        return;
    }
    QPointF oldpos = _item->pos();
    _item->setPos(oldpos.x(), v);
    QPointF newPos = _item->pos();
    QSignalBlocker b1(ui->doubleSpinBoxX), b2(ui->doubleSpinBoxY);
    Q_UNUSED(b1);
    Q_UNUSED(b2);
    ui->doubleSpinBoxX->setValue(newPos.x());
    ui->doubleSpinBoxY->setValue(newPos.y());
    if (_scene) {
        auto cmd = new DA::DACommandsForGraphicsItemMoved(_item, oldpos, newPos, true);
        _scene->push(cmd);
    }
}

void DANodeItemSettingWidget::onCheckBoxMovableStateChanged(int state)
{
    if (_item) {
        _item->setFlag(QGraphicsItem::ItemIsMovable, state == Qt::Checked);
        ui->doubleSpinBoxX->setEnabled(_item->isMovable());
        ui->doubleSpinBoxY->setEnabled(_item->isMovable());
    }
}

void DANodeItemSettingWidget::onCheckBoxResizableStateChanged(int state)
{
    if (_item) {
        _item->setEnableResize(state == Qt::Checked);
        _item->update();
        ui->doubleSpinBoxBodyWidth->setEnabled(_item->isEnableResize());
        ui->doubleSpinBoxBodyHeight->setEnabled(_item->isEnableResize());
    }
}

void DANodeItemSettingWidget::onNodeItemsRemoved(const QList< DAAbstractNodeGraphicsItem* >& items)
{
    for (const DAAbstractNodeGraphicsItem* i : qAsConst(items)) {
        if (i == _item) {
            _item = nullptr;
            updateData();
        }
    }
}

void DANodeItemSettingWidget::resetValue()
{
    ui->doubleSpinBoxBodyWidth->setValue(0);
    ui->doubleSpinBoxBodyHeight->setValue(0);
    ui->doubleSpinBoxRotation->setValue(0);
    ui->doubleSpinBoxX->setValue(0);
    ui->doubleSpinBoxY->setValue(0);
    ui->checkBoxMovable->setChecked(false);
    ui->checkBoxResizable->setChecked(false);
    ui->textEdit->setText("");
}
